package com.gegao.somethinginteresting.player;

import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.Surface;
import android.widget.MediaController;

import com.gegao.somethinginteresting.entity.MusicInfoWapper;
import com.google.android.exoplayer.ExoPlayer;
import com.google.android.exoplayer.util.PlayerControl;
import com.google.android.exoplayer.util.Util;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * 播放器的管理器
 * Created by liuchenghui on 2015/11/09.
 */
public class EXOPlayerManager implements EXOPlayerBuilder.Listener {

    private static final int PLAY_MODEL_SINGLE = 1;
    private static final int PLAY_MODEL_SINGLE_CYCLE = 2;
    private static final int PLAY_MODEL_ALL = 3;
    private static final int PLAY_MODEL_ALL_CYCLE = 4;
    private static final int PLAY_MODEL_ALL_RANDOM = 5;

    private int playModel = PLAY_MODEL_ALL_CYCLE;//当前的播放模式
    private boolean lastReportedPlayWhenReady = false;//上次的是否播放
    private int lastReportedPlaybackState = ExoPlayer.STATE_IDLE;//上次的播放状态

    private static final int UPDATA_PLAY_PROGRESS = 6;
    private static final int UPDATA_BUFFERING_PROGRESS = 7;
    private static final int CHECK_PLAYBACKSTATE = 8;

    private static EXOPlayerManager EXOPlayerManager;
    private static EXOPlayerBuilder EXOPlayerBuilder;
    private static Context mContext;
    private PlayerControl playerControl;
    private String userAgent;

    private List<MusicInfoWapper> musicInfoWapperList = new ArrayList<>();
    private MusicInfoWapper currentPlaySong;
    private int currentPlaySongPosition;
    private List<PlayerStatusChangerListener> statusChangerListeners = new ArrayList<>();
    private List<PlayerProgressListener> progressListeners = new ArrayList<>();

    private int pos;
    private int bufferPercentage;
    private Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case UPDATA_PLAY_PROGRESS://更新播放进度
                    if (playerControl != null) {
                        pos = playerControl.getCurrentPosition();
                        for (PlayerProgressListener listener : progressListeners) {
                            int totle = playerControl.getDuration();
                            if (totle > 0) {
                                listener.onUpdatePlayProgress(pos, totle);
                            }
                        }
                    }
//                    if (playerControl.isPlaying()) {
                    msg = handler.obtainMessage(UPDATA_PLAY_PROGRESS);
                    handler.sendMessageDelayed(msg, 42/*1000 - (pos % 1000)*/);
//                    }
                    break;

                case UPDATA_BUFFERING_PROGRESS://更新缓存进度
                    if (playerControl != null) {
                        bufferPercentage = playerControl.getBufferPercentage();
                        for (PlayerProgressListener listener : progressListeners) {
                            listener.onUpdateBufferingProgress(bufferPercentage);
                        }
                    }
//                    if (playerControl.isPlaying()) {
                    msg = handler.obtainMessage(UPDATA_BUFFERING_PROGRESS);
                    handler.sendMessageDelayed(msg, 1000 - (pos % 1000));
//                    }
//                    if(bufferPercentage==100){
//                        handler.removeMessages(UPDATA_BUFFERING_PROGRESS);
//                    }
                    break;
                case CHECK_PLAYBACKSTATE:
                    if (lastReportedPlaybackState == EXOPlayerBuilder.STATE_BUFFERING) {
                        for (PlayerStatusChangerListener listener : statusChangerListeners) {
                            listener.onPlayerStartBuffering();
                        }
                    }
                    break;
            }
            return false;
        }
    });

    private EXOPlayerManager() {
    }

    public static EXOPlayerManager getInstance(Context context) {
        setContext(context);
        return getInstance();
    }

    private static EXOPlayerManager getInstance() {
        if (EXOPlayerManager == null)
            EXOPlayerManager = new EXOPlayerManager();
        return EXOPlayerManager;
    }

    public static void setContext(Context context) {
        if (mContext == null)
            mContext = context;
    }

    /**
     * 构建播放器的数据
     *
     * @param musicInfoWapper 内容
     * @return EXOPlayerBuilder{@link EXOPlayerBuilder}
     */
    private EXOPlayerBuilder buildePlayerData(MusicInfoWapper musicInfoWapper) throws Exception {
        Uri uri;
        if (TextUtils.isEmpty(userAgent))
            userAgent = Util.getUserAgent(mContext, "Ising");
        if (!TextUtils.isEmpty(musicInfoWapper.getMusicPlayUrl())) {
            uri = Uri.parse(musicInfoWapper.getMusicPlayUrl());
        } else {
            throw new Exception("media url is invalid");
        }
        if (EXOPlayerBuilder == null) {
            EXOPlayerBuilder = new EXOPlayerBuilder(new ExtractorRendererBuilder(mContext, userAgent, uri));
            EXOPlayerBuilder.addListener(this);
        } else {
            playerControl.seekTo(0);
            EXOPlayerBuilder.replaceRenderBuilder(new ExtractorRendererBuilder(mContext, userAgent, uri));
        }
        if (playerControl == null)
            playerControl = EXOPlayerBuilder.getPlayerControl();
        currentPlaySong = musicInfoWapper;
        if (statusChangerListeners != null && statusChangerListeners.size() > 0)
            for (PlayerStatusChangerListener listeners : statusChangerListeners) {
                listeners.onPlayerLoadDataComplete();
            }
        return EXOPlayerBuilder;
    }

    /**
     * 播放或继续播放
     *
     * @param musicInfoWapper
     */
    public void play(MusicInfoWapper musicInfoWapper) {
        try {
            buildePlayerData(musicInfoWapper);
        } catch (Exception e) {
            e.printStackTrace();
        }
        start();
    }

    /**
     * 暂停播放
     */
    public void pause() {
        if (EXOPlayerBuilder != null) {
            EXOPlayerBuilder.setPlayWhenReady(false);
        }
    }

    /**
     * 恢复播放
     */
    public void start() {
        if (EXOPlayerBuilder != null && playerControl != null && !playerControl.isPlaying()) {
            EXOPlayerBuilder.prepare();
            EXOPlayerBuilder.setPlayWhenReady(true);
        }
    }

    /**
     * 停止播放
     */
    public void stop() {
        if (EXOPlayerBuilder != null) {
            EXOPlayerBuilder.seekTo(0);
            EXOPlayerBuilder.setPlayWhenReady(false);
//            EXOPlayerBuilder.stop();
            for (PlayerStatusChangerListener listener : statusChangerListeners) {
                listener.onPlayerStop();
            }
        }
    }

    public void resume() {
        if (EXOPlayerBuilder != null) {
            EXOPlayerBuilder.setPlayWhenReady(true);
        }
    }


    /**
     * 播放当前列表指定position的歌曲
     *
     * @param musicInfoWapperList
     * @param position
     */
    public void playCurrentSongListAtPosition(List<MusicInfoWapper> musicInfoWapperList, int position) {
        if (musicInfoWapperList != null && musicInfoWapperList.size() > 0 && musicInfoWapperList.size() > position) {
            setmusicInfoWapperList(musicInfoWapperList);
            currentPlaySongPosition = position;
            play(musicInfoWapperList.get(position));
        }
    }

    /**
     * 播放单独的歌曲（非列表）
     *
     * @param musicInfoWapper
     */
    public void playSingleSong(MusicInfoWapper musicInfoWapper) {
        if (musicInfoWapper != null) {
            List<MusicInfoWapper> temp = new ArrayList<>();
            temp.add(musicInfoWapper);
            playCurrentSongListAtPosition(temp, 0);
        }
    }

    /**
     * 播放列表中的下一首歌
     */
    public void playNextSongFromList() {
        MusicInfoWapper nextSongFromList = getNextSongFromList();
        if (nextSongFromList != null) {
            exoPlayerStatusInfos.clear();
            play(nextSongFromList);
            //添加一个回调(播放下一曲)
            if (statusChangerListeners != null && statusChangerListeners.size() > 0) {
                for (PlayerStatusChangerListener listener : statusChangerListeners) {
                    if (listener != null)
                        listener.onPlayerPlayNextSong();
                }
            }
        }
    }

    /**
     * 播放列表中的前一首歌
     */
    public void playpreviousSongFromList() {
        MusicInfoWapper previousSongFromList = getpreviousSongFromList();
        if (previousSongFromList != null) {
            play(previousSongFromList);
        }
    }

    /**
     * 重播当前的歌曲
     */
    public void rePlayCurrentSong() {
        if (currentPlaySong != null) {
            play(currentPlaySong);
        } else if (currentPlaySong == null && musicInfoWapperList != null && musicInfoWapperList.size() > 0 && musicInfoWapperList.size() > currentPlaySongPosition) {
            play(musicInfoWapperList.get(currentPlaySongPosition));
        }
    }

    //==============内部逻辑方法=========================================

    /**
     * @return 获取列表中的下一首
     */
    private MusicInfoWapper getNextSongFromList() {
        switch (playModel) {
            case PLAY_MODEL_ALL_CYCLE:
                if (musicInfoWapperList == null || musicInfoWapperList.size() < 1)
                    return null;
                if (currentPlaySongPosition + 1 > musicInfoWapperList.size() - 1) {
                    currentPlaySongPosition = 0;
                    return musicInfoWapperList.get(currentPlaySongPosition);
                } else {
                    return musicInfoWapperList.get(++currentPlaySongPosition);
                }
            case PLAY_MODEL_ALL_RANDOM:
                break;
            case PLAY_MODEL_ALL:
                break;
            case PLAY_MODEL_SINGLE:
                return null;
            case PLAY_MODEL_SINGLE_CYCLE:
                break;
        }
        return null;
    }

    /**
     * @return 获取列表中的前一首
     */
    private MusicInfoWapper getpreviousSongFromList() {
        switch (playModel) {
            case PLAY_MODEL_ALL_CYCLE:
                break;
            case PLAY_MODEL_ALL_RANDOM:
                break;
            case PLAY_MODEL_ALL:
                break;
            case PLAY_MODEL_SINGLE:
                break;
            case PLAY_MODEL_SINGLE_CYCLE:
                break;
        }
        return null;
    }

    //==============各种getter和setter===============================================================

    /**
     * 设置播放列表的类容
     *
     * @param temp
     */
    private void setmusicInfoWapperList(List<MusicInfoWapper> temp) {
        if (temp == null)
            return;
        if (this.musicInfoWapperList == null)
            this.musicInfoWapperList = new ArrayList<>();
        this.musicInfoWapperList.clear();
        this.musicInfoWapperList.addAll(temp);
    }

    public int getDuration() {
        if (playerControl != null) {
            return playerControl.getDuration();
        }
        return 0;
    }

    public void setmusicInfoWapper(MusicInfoWapper musicInfoWapper) {
        try {
            buildePlayerData(musicInfoWapper);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 调整当前播放的进度
     *
     * @param positionMs
     */
    public void seekTo(long positionMs) {
        if (EXOPlayerBuilder != null)
            EXOPlayerBuilder.seekTo(positionMs);
    }

    /**
     * 设置播放视频的surface
     *
     * @param surface 要显示的地方
     */
    public void setSurface(Surface surface) {
        if (surface != null)
            EXOPlayerBuilder.setSurface(surface);
    }

    /**
     * 获取surface
     *
     * @return Surface
     */
    public Surface getSurface() {
        if (EXOPlayerBuilder != null) {
            return EXOPlayerBuilder.getSurface();
        } else {
            return null;
        }
    }

    /**
     * 移除正在显示的surface（阻塞）
     */
    public void blockingClearSurface() {
        EXOPlayerBuilder.blockingClearSurface();
    }

    /**
     * 获取音乐播放控制器
     *
     * @return MediaPlayerControl
     */
    public MediaController.MediaPlayerControl getController() {
        if (playerControl != null) {
            return playerControl;
        } else {
            if (EXOPlayerBuilder != null) {
                return EXOPlayerBuilder.getPlayerControl();
            }
        }
        return null;
    }

    public MusicInfoWapper getmusicInfoWapper() {
        return currentPlaySong;
    }

    public boolean isPlaying() {
        return isPlaying;
    }

    public boolean getPlayWhenReadyStatus() {
        if (EXOPlayerBuilder != null) {
            return EXOPlayerBuilder.getPlayWhenReady();
        } else {
            return false;
        }
    }

    public void setStatuChangerListener(PlayerStatusChangerListener statuChangerListener) {
        if (statuChangerListener != null && !statusChangerListeners.contains(statuChangerListener))
            statusChangerListeners.add(statuChangerListener);
    }

    public void removeStatuChangerListener(PlayerStatusChangerListener statuChangerListener) {
        statusChangerListeners.remove(statuChangerListener);
    }

    public void setUpdateProgressListener(PlayerProgressListener progressListener) {
        if (progressListener != null && !progressListeners.contains(progressListener))
            progressListeners.add(progressListener);
    }

    public void removeUpdateProgressListener(PlayerProgressListener progressListener) {
        progressListeners.remove(progressListener);
    }

    //player的各种回掉==================================================================================
    List<ExoPlayerStatusInfo> exoPlayerStatusInfos = new LinkedList<>();
    private static final int LISTMOSTLENGTH = 3;
    private static final int CURRENT_STATUS_IN_LIST = 0;
    private static final int LAST_STATUS_IN_LIST = 1;
    private static final int BEFORE_LAST_STATUS_IN_LIST = 2;
    private boolean isPlaying = false;

    @Override
    public void onStateChanged(boolean playWhenReady, int playbackState) {
        System.out.println("playWhenReady-->" + playWhenReady + "     playbackState-->" + playbackState);
        if (exoPlayerStatusInfos != null) {
            if (exoPlayerStatusInfos.size() >= LISTMOSTLENGTH) {
                exoPlayerStatusInfos.remove(exoPlayerStatusInfos.size() - 1);
            }
            exoPlayerStatusInfos.add(0, new ExoPlayerStatusInfo(playWhenReady, playbackState));
        } else {
            exoPlayerStatusInfos = new ArrayList<>();
        }

        //刚刚载入消息
        if (playbackState == ExoPlayer.STATE_PREPARING) {
            isPlaying = false;
            for (PlayerStatusChangerListener listener : statusChangerListeners) {
                listener.onPlayerPrepare();
            }
        }

        //表示prepare --> buffering   从新初始化
        if (exoPlayerStatusInfos.size() >= 2 && exoPlayerStatusInfos.get(CURRENT_STATUS_IN_LIST).getPlaybackState() == ExoPlayer.STATE_BUFFERING
                && exoPlayerStatusInfos.get(LAST_STATUS_IN_LIST).getPlaybackState() == ExoPlayer.STATE_PREPARING) {
            isPlaying = false;
            handler.sendEmptyMessage(UPDATA_PLAY_PROGRESS);
            System.out.println("statusChange:  重新初始化 --->listener.onLoadPlayInfo()");
            for (PlayerStatusChangerListener listener : statusChangerListeners) {
                listener.onLoadPlayInfo();
            }
        }

        //表示prepare --> buffering --> ready  从新初始化完成，可以开始播放
        if (exoPlayerStatusInfos.size() >= 3 && exoPlayerStatusInfos.get(CURRENT_STATUS_IN_LIST).getPlaybackState() == ExoPlayer.STATE_READY
                && exoPlayerStatusInfos.get(LAST_STATUS_IN_LIST).getPlaybackState() == ExoPlayer.STATE_BUFFERING
                && exoPlayerStatusInfos.get(BEFORE_LAST_STATUS_IN_LIST).getPlaybackState() == ExoPlayer.STATE_PREPARING) {
            isPlaying = true;
            System.out.println("statusChange:  初始化，完毕。开始播放 --->listener.onLoadPlayInfo()");
            for (PlayerStatusChangerListener listener : statusChangerListeners) {
                listener.onPlayerPlay();
            }
        }

        //恢复
        if (exoPlayerStatusInfos.size() >= 2
                & (lastReportedPlaybackState != ExoPlayer.STATE_ENDED && lastReportedPlaybackState != ExoPlayer.STATE_IDLE)
                && lastReportedPlayWhenReady == false && playWhenReady) {
            isPlaying = true;
            System.out.println("statusChange:  恢复 --->listener.onPlayerResume()");
            handler.sendEmptyMessage(UPDATA_PLAY_PROGRESS);
            for (PlayerStatusChangerListener listener : statusChangerListeners) {
                listener.onPlayerResume();
            }
        }

        //暂停
        if (exoPlayerStatusInfos.size() >= 2 &&
                lastReportedPlayWhenReady == true && !playWhenReady) {
            System.out.println("statusChange:  暂停 --->listener.onPlayerPause()");
            isPlaying = false;
            handler.removeMessages(UPDATA_PLAY_PROGRESS);
            for (PlayerStatusChangerListener listener : statusChangerListeners) {
                listener.onPlayerPause();
            }

        }

        //播放完成  ready --> end
        if (lastReportedPlaybackState == ExoPlayer.STATE_READY && playbackState == ExoPlayer.STATE_ENDED) {
            System.out.println("statusChange:  播放完一曲 --->listener.onPlayerEnd()");
            isPlaying = false;
            if (playerControl != null)
                playerControl.seekTo(0);
            handler.removeMessages(UPDATA_BUFFERING_PROGRESS);
            handler.removeMessages(UPDATA_PLAY_PROGRESS);
            for (PlayerStatusChangerListener listener : statusChangerListeners) {
                if (playWhenReady)
                    listener.onPlayerEnd();
            }
        }


        //播放着网速不够，或者点击seekbar到没缓冲到的地方，开始缓冲
        if ((lastReportedPlayWhenReady && lastReportedPlaybackState == ExoPlayer.STATE_READY) && (playWhenReady && playbackState == ExoPlayer.STATE_BUFFERING)) {
            isPlaying = false;
            handler.sendEmptyMessage(UPDATA_BUFFERING_PROGRESS);
            handler.sendEmptyMessageDelayed(CHECK_PLAYBACKSTATE, 300);
        }

        //跟上面那个相反
        if ((lastReportedPlayWhenReady && lastReportedPlaybackState == ExoPlayer.STATE_BUFFERING) && (playWhenReady && playbackState == ExoPlayer.STATE_READY)) {
            isPlaying = true;
            for (PlayerStatusChangerListener listener : statusChangerListeners) {
                listener.onPlayerafterBuffering(playWhenReady);
            }
        }

        lastReportedPlayWhenReady = playWhenReady;
        lastReportedPlaybackState = playbackState;
    }

    @Override
    public void onError(Exception e) {

    }

    @Override
    public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {

    }

}
